zhouqijie

序、OpenGL渲染管线


从C++应用程序

顶点着色器

曲面细分着色器

几何着色器

光栅化

片段着色器

像素操作




一、顶点着色器和片段着色器的创建

要绘制东西,需要加入顶点着色器和片段着色器。绘制的基本单位是图元(点、线、三角形等)。

三维模型通常是由许多三角形图元构成的。

示例:绘制一个白点

#define numVAOs 1

GLuint renderingProgram;//声明渲染程序对象
GLuint vao[numVAOs];

//创建渲染程序对象的函数
GLuint createShaderProgram()
{
	//GLSL源代码
	const char * vshaderSource =
		"#version 430 \n"
		"void main(void) \n"
		"{ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }"
		;
	const char * fshaderSource =
		"#version 430 \n"
		"out vec4 color; \n"
		"void main(void) \n"
		"{ color = vec4(1.0, 1.0, 1.0, 1.0); }"
		;

	//创建空着色器对象
	GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
	//载入着色器源码并编译
	glShaderSource(vShader, 1, &vshaderSource, NULL);
	glShaderSource(fShader, 1, &fshaderSource, NULL);
	glCompileShader(vShader);
	glCompileShader(fShader);
	//创建渲染程序并附加着色器。然后请求GLSL编译器确保兼容性。
	GLuint vfProgram = glCreateProgram();
	glAttachShader(vfProgram, vShader);
	glAttachShader(vfProgram, fShader);
    glLinkProgram(vfProgram);

	return vfProgram;
}

初始化:

void init(GLFWwindow * window) 
{ 
	//指定渲染程序
	renderingProgram = createShaderProgram();
	//创建OpenGL要求的VAO(顶点数组对象)。
	glGenVertexArrays(numVAOs, vao);
	glBindVertexArray(vao[0]);
}

渲染:

//渲染
void display(GLFWwindow * window, double currentTime)
{
	glUseProgram(renderingProgram);//把编译好的着色器程序加载进GPU硬件的OpenGL渲染管线。
	glDrawArrays(GL_POINTS, 0, 1);//绘制一个点
}

相关宏定义:

GLuint:平台无关的整型简写。(许多OpenGL结构体都是整形引用)(句柄?)

GL_VERTEX_SHADER:作函数glCreateShader()参数,表示要创建的是顶点着色器。

GL_FRAGMENT_SHADER:作函数glCreateShader()参数,表示要创建的是片元着色器。

程序对象:

在init()函数中指定渲染程序对象renderingProgram。

创建程序对象的函数:

定义一个createShaderProgram函数来创建渲染程序。

1.定义着色器源代码vShaderSourcefShaderSource
2.调用glCreateShader()函数创建了顶点和片元两个Shader并返回整数句柄作为后面引用它的序号。
3.调用glShaderSource()将GLSL源代码载入空着色器中。

4.调用glCompileShader()编译各着色器。
5.调用glCreateProgram() 创建程序对象vfProgram,然后使用glAttachShader()把两个着色器附加上去,然后使用glLinkProgram()请求GLSL编译器确定它们的兼容性。
6.最后返回该vfProgram程序对象。

初始化:

使用glGenVertexArrays()glBindVertexArray()来创建OpenGL要求的VAO(顶点数组对象)。


渲染:

1.使用glUseProgram(renderingProgram)把已经编译的着色器程序载入GPU上的OpenGL渲染管线。(这一步没有运行着色器,只是加载进硬件)

2.绘制三角形:OpenGL通过函数glDrawArrays(GLeum mode, GLint first, GLsizei count);完成三角形绘制。

不管从何处读入,所有顶点都会被传入顶点着色器。着色器会对每个顶点执行一次,这些执行过程通常是并行的。


二、关于光栅化过程

光栅化将图元(通常是三角形)转换成片段。光栅化过程确定了用于绘制三角形的所有像素位置。

光栅化过程会对三角形进行顶点插值,通常使用简单的线性插值。任何顶点着色器输出变量/片段着色器输入变量都可以进行插值。

补充:点的光栅化默认一个像素,可以通过glPointSize()指定点的渲染大小。

三、关于片段着色器和像素操作

概述:

片段着色器用于为光栅化的像素指定颜色。

片段坐标:

顶点着色器使用预定义变量gl_Position输出坐标(NDC坐标)。在片段着色器中可以通过gl_FragCoord访问插值过后的输入片段坐标(屏幕坐标)。

Z-Buffer算法:

Z-Buffer算法可以利用颜色缓存和深度缓存两个缓冲区,配合深度测试,来进行遮挡效果的实现(HSR)。

四:关于曲面细分着色器

可编程曲面细分阶段是新加入OpenGL的功能,用于生成大量三角形。
用GPU中的曲面细分着色器在硬件里生成三角形网络比在C++中生成要高效得多。

五:关于几何着色器

使用几何着色器可以一次操作一个图元。(对应顶点着色器可一次操作一个顶点,片段着色器可一次操作一个像素。)
几何着色器主要用途有:图元拉伸缩小、删除图元、生成额外图元、生成凹凸等。

补充:常见图元类型

GL_POINTS: 点

GL_LINES: 线

管线中每两个顶点组成一条线。

GL_LINES_STRIP: 线

管线中每个顶点和前一个顶点组成一条线。

GL_LINES_LOOP: 线

同上,但是第一个和最后一个也会组成一条线。

GL_TRIANGLES: 三角形

管线中每三个顶点组成一个三角形。

GL_TRIANGLES_STRIP: 三角形

管线中每个顶点与它之前两个顶点组成一个三角形。

GL_TRIANGLES_FAN: 三角形

管线中传递的每个顶点和它后面的那个顶点以及最开始的第一个顶点组成一个三角形。